home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2000 #5 / Amiga Plus CD - 2000 - No. 5.iso / Tools / Dev / GameboyDev / GBDK / lib / crt0.s < prev    next >
Text File  |  1999-03-29  |  8KB  |  563 lines

  1.     .include    "global.s"
  2.  
  3.     ;; ****************************************
  4.     ;; Beginning of module
  5.     .title    "GB Runtime"
  6.     .module    Runtime
  7.     .area    _HEADER (ABS)
  8.  
  9.     ;; Standard header for the GB
  10.     .org    0x00
  11.     RET            ; Empty function (default for interrupts)
  12.  
  13.     .org    0x10
  14.     .byte    0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01
  15.     .byte    0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
  16.  
  17.     ;; Interrupt vectors
  18.     .org    0x40        ; VBL
  19. .int_VBL:
  20.     PUSH    HL
  21.     LD    HL,#.int_0x40
  22.     JP    .int
  23.  
  24.     .org    0x48        ; LCD
  25. .int_LCD:
  26.     PUSH    HL
  27.     LD    HL,#.int_0x48
  28.     JP    .int
  29.  
  30.     .org    0x50        ; TIM
  31. .int_TIM:
  32.     PUSH    HL
  33.     LD    HL,#.int_0x50
  34.     JP    .int
  35.  
  36.     .org    0x58        ; SIO
  37. .int_SIO:
  38.     PUSH    HL
  39.     LD    HL,#.int_0x58
  40.     JP    .int
  41.  
  42.     .org    0x60        ; JOY
  43. .int_JOY:
  44.     PUSH    HL
  45.     LD    HL,#.int_0x60
  46.     JP    .int
  47.  
  48. .int:
  49.     PUSH    AF
  50.     PUSH    BC
  51.     PUSH    DE
  52. 1$:
  53.     LD    A,(HL+)
  54.     OR    (HL)
  55.     JR    Z,2$
  56.     PUSH    HL
  57.     LD    A,(HL-)
  58.     LD    L,(HL)
  59.     LD    H,A
  60.     CALL    3$
  61.     POP    HL
  62.     INC    HL
  63.     JR    1$
  64. 2$:
  65.     POP    DE
  66.     POP    BC
  67.     POP    AF
  68.     POP    HL
  69.     RETI
  70.  
  71. 3$:
  72.     JP    (HL)
  73.  
  74.     ;; GameBoy Header
  75.  
  76.     ;; DO NOT CHANGE...
  77.     .org    0x100
  78. .header:
  79.     NOP
  80.     JP    0x150
  81.     .byte    0xCE,0xED,0x66,0x66
  82.     .byte    0xCC,0x0D,0x00,0x0B
  83.     .byte    0x03,0x73,0x00,0x83
  84.     .byte    0x00,0x0C,0x00,0x0D
  85.     .byte    0x00,0x08,0x11,0x1F
  86.     .byte    0x88,0x89,0x00,0x0E
  87.     .byte    0xDC,0xCC,0x6E,0xE6
  88.     .byte    0xDD,0xDD,0xD9,0x99
  89.     .byte    0xBB,0xBB,0x67,0x63
  90.     .byte    0x6E,0x0E,0xEC,0xCC
  91.     .byte    0xDD,0xDC,0x99,0x9F
  92.     .byte    0xBB,0xB9,0x33,0x3E
  93.  
  94.     ;; Title of the game
  95.     .org    0x134
  96.     .asciz    "Title"
  97.  
  98.     .org    0x144
  99.     .byte    0,0,0
  100.  
  101.     ;; Cartridge type is ROM only
  102.     .org    0x147
  103.     .byte    0
  104.  
  105.     ;; ROM size is 32kB
  106.     .org    0x148
  107.     .byte    0
  108.  
  109.     ;; RAM size is 0kB
  110.     .org    0x149
  111.     .byte    0
  112.  
  113.     ;; Maker ID
  114.     .org    0x14A
  115.     .byte    0x00,0x00
  116.  
  117.     ;; Version number
  118.     .org    0x14C
  119.     .byte    0x01
  120.  
  121.     ;; Complement check
  122.     .org    0x14D
  123.     .byte    0x00
  124.  
  125.     ;; Checksum
  126.     .org    0x14E
  127.     .byte    0x00,0x00
  128.  
  129.     ;; ****************************************
  130.     .org    0x150
  131. .code_start:
  132.     ;; Beginning of the code
  133.     DI            ; Disable interrupts
  134.     LD    D,A        ; Store CPU type in D
  135.     XOR    A
  136.     ;; Initialize the stack
  137.     LD    SP,#.STACK
  138.     ;; Clear from 0xC000 to 0xDFFF
  139.     LD    HL,#0xDFFF
  140.     LD    C,#0x20
  141.     LD    B,#0x00
  142. 1$:
  143.     LD    (HL-),A
  144.     DEC    B
  145.     JR    NZ,1$
  146.     DEC    C
  147.     JR    NZ,1$
  148.     ;; Clear from 0xFE00 to 0xFEFF
  149.     LD    HL,#0xFEFF
  150.     LD    B,#0x00
  151. 2$:
  152.     LD    (HL-),A
  153.     DEC    B
  154.     JR    NZ,2$
  155.     ;; Clear from 0xFF80 to 0xFFFF
  156.     LD    HL,#0xFFFF
  157.     LD    B,#0x80
  158. 3$:
  159.     LD    (HL-),A
  160.     DEC    B
  161.     JR    NZ,3$
  162. ;     LD    (.mode),A    ; Clearing (.mode) is performed when clearing RAM
  163.     ;; Store CPU type
  164.     LD    A,D
  165.     LD    (__cpu),A
  166.  
  167.     ;; Turn the screen off
  168.     CALL    .display_off
  169.  
  170.     ;; Initialize the display
  171.     XOR    A
  172.     LDH    (.SCY),A
  173.     LDH    (.SCX),A
  174.     LDH    (.STAT),A
  175.     LDH    (.WY),A
  176.     LD    A,#0x07
  177.     LDH    (.WX),A
  178.  
  179.     ;; Copy refresh_OAM routine to HIRAM
  180.     LD    BC,#.refresh_OAM
  181.     LD    HL,#.start_refresh_OAM
  182.     LD    B,#.end_refresh_OAM-.start_refresh_OAM
  183. 4$:
  184.     LD    A,(HL+)
  185.     LDH    (C),A
  186.     INC    C
  187.     DEC    B
  188.     JR    NZ,4$
  189.  
  190.     ;; Install interrupt routines
  191.     LD    BC,#.vbl
  192.     CALL    .add_VBL
  193.     LD    BC,#.serial_IO
  194.     CALL    .add_SIO
  195.  
  196.     ;; Standard color palettes
  197.     LD    A,#0b11100100    ; Grey 3 = 11 (Black)
  198.                 ; Grey 2 = 10 (Dark grey)
  199.                 ; Grey 1 = 01 (Light grey)
  200.                 ; Grey 0 = 00 (Transparent)
  201.     LDH    (.BGP),A
  202.     LDH    (.OBP0),A
  203.     LD    A,#0b00011011
  204.     LDH    (.OBP1),A
  205.  
  206.     ;; Turn the screen on
  207.     LD    A,#0b11000000    ; LCD        = On
  208.                 ; WindowBank    = 0x9C00
  209.                 ; Window    = Off
  210.                 ; BG Chr    = 0x8800
  211.                 ; BG Bank    = 0x9800
  212.                 ; OBJ        = 8x8
  213.                 ; OBJ        = Off
  214.                 ; BG        = Off
  215.     LDH    (.LCDC),A
  216.     XOR    A
  217.     LDH    (.IF),A
  218.     LD    A,#0b00001001    ; Pin P10-P13    =   Off
  219.                 ; Serial I/O    =   On
  220.                 ; Timer Ovfl    =   Off
  221.                 ; LCDC        =   Off
  222.                 ; V-Blank    =   On
  223.     LDH    (.IE),A
  224.  
  225.     XOR    A
  226.     LDH    (.NR52),A    ; Turn sound off
  227.     LDH    (.SC),A        ; Use external clock
  228.     LD    A,#.DT_IDLE
  229.     LDH    (.SB),A        ; Send IDLE byte
  230.     LD    A,#0x80
  231.     LDH    (.SC),A        ; Use external clock
  232.  
  233.     XOR    A        ; Erase the malloc list
  234.     LD    (_malloc_heap_start+0),A
  235.     LD    (_malloc_heap_start+1),A
  236.     LD    (.sys_time+0),A    ; Zero the system clock
  237.     LD    (.sys_time+1),A    
  238.  
  239.     CALL    .init
  240.  
  241.     EI            ; Enable interrupts
  242.  
  243.     ;; Call the main function
  244.     CALL    _main
  245.  
  246. 99$:
  247.     JR    99$        ; Wait forever
  248.  
  249.     .org    .MODE_TABLE
  250.     ;; Jump table for modes
  251.     RET
  252.  
  253.     ;; ****************************************
  254.  
  255.     ;; Ordering of segments for the linker
  256.     .area    _CODE
  257.     .area    _DATA
  258.     .area    _LIT
  259.     .area    _BSS
  260.     .area    _HEAP        ; HEAP is for malloc
  261.  
  262.     .area    _BSS
  263.  
  264. __cpu::
  265.     .ds    0x01        ; GB type (GB, PGB, CGB)
  266. .mode::
  267.     .ds    0x01        ; Current mode
  268. __io_out::
  269.     .ds    0x01        ; Byte to send
  270. __io_in::
  271.     .ds    0x01        ; Received byte
  272. __io_status::
  273.     .ds    0x01        ; Status of serial IO
  274. .vbl_done::
  275.     .ds    0x01        ; Is VBL interrupt finished?
  276. .sys_time::
  277. _sys_time::
  278.     .ds    0x02        ; System time in VBL units
  279. .int_0x40::
  280.     .blkw    0x08
  281. .int_0x48::
  282.     .blkw    0x08
  283. .int_0x50::
  284.     .blkw    0x08
  285. .int_0x58::
  286.     .blkw    0x08
  287. .int_0x60::
  288.     .blkw    0x08
  289.  
  290.     ;; Runtime library
  291.     .area    _CODE
  292.  
  293.     ;; Call the initialization function for the mode specified in HL
  294. .set_mode::
  295.     LD    A,L
  296.     LD    (.mode),A
  297.  
  298.     ;; AND to get rid of the extra flags
  299.     AND    #0x03
  300.     LD    L,A
  301.     LD    BC,#.MODE_TABLE
  302.     SLA    L        ; Multiply mode by 4
  303.     SLA    L
  304.     ADD    HL,BC
  305.     JP    (HL)        ; Jump to initialization routine
  306.  
  307.     ;; Add interrupt routine in BC to the interrupt list
  308. .add_VBL::
  309.     LD    HL,#.int_0x40
  310.     JP    .add_int
  311. .add_LCD::
  312.     LD    HL,#.int_0x48
  313.     JP    .add_int
  314. .add_TIM::
  315.     LD    HL,#.int_0x50
  316.     JP    .add_int
  317. .add_SIO::
  318.     LD    HL,#.int_0x58
  319.     JP    .add_int
  320. .add_JOY::
  321.     LD    HL,#.int_0x60
  322.     JP    .add_int
  323.  
  324.     ;; Remove interrupt BC from interrupt list HL if it exists
  325.     ;; Abort if a 0000 is found (end of list)
  326.     ;; Will only remove last int on list
  327. .remove_int::
  328. 1$:
  329.     LD    A,(HL+)
  330.     LD    E,A
  331.     LD    D,(HL)
  332.     OR    D
  333.     RET    Z        ; No interrupt found
  334.  
  335.     LD    A,E
  336.     CP    C
  337.     JR    NZ,1$
  338.     LD    A,D
  339.     CP    B
  340.     JR    NZ,1$
  341.  
  342.     XOR    A
  343.     LD    (HL-),A
  344.     LD    (HL),A
  345.     INC    A        ; Clear Z flag
  346.     RET
  347.     
  348.     ;; Add interrupt routine in BC to the interrupt list in HL
  349. .add_int::
  350. 1$:
  351.     LD    A,(HL+)
  352.     OR    (HL)
  353.     JR    Z,2$
  354.     INC    HL
  355.     JR    1$
  356. 2$:
  357.     LD    (HL),B
  358.     DEC    HL
  359.     LD    (HL),C
  360.     RET
  361.  
  362.     
  363.     ;; VBlank interrupt
  364. .vbl:
  365.     LD    HL,#.sys_time
  366.     INC    (HL)
  367.     JR    NZ,2$
  368.     INC    HL
  369.     INC    (HL)
  370. 2$:    
  371.     CALL    .refresh_OAM
  372.  
  373.     .if    0
  374.     ;; Verify that only one VBlank interrupt occured
  375.     LD    A,(.vbl_done)
  376.     OR    A
  377.     JR    Z,1$
  378.     LDH    A,(.BGP)
  379.     CPL
  380.     LDH    (.BGP),A
  381. 1$:
  382.     .endif
  383.  
  384.     LD    A,#0x01
  385.     LD    (.vbl_done),A
  386.     RET
  387.  
  388.     ;; Wait for VBL interrupt to be finished
  389. .wait_vbl_done::
  390. _wait_vbl_done::
  391.     ;; Check if the screen is on
  392.     LDH    A,(.LCDC)
  393.     ADD    A
  394.     RET    NC        ; Return if screen is off
  395. 1$:
  396.     HALT            ; Wait for any interrupt
  397.     NOP            ; HALT sometimes skips the next instruction
  398.     LD    A,(.vbl_done)    ; Was it a VBlank interrupt?
  399.     ;; Warning: we may lose a VBlank interrupt, if it occurs now
  400.     OR    A
  401.     JR    Z,1$        ; No: back to sleep!
  402.  
  403.     XOR    A
  404.     LD    (.vbl_done),A
  405.     RET
  406.  
  407. .display_off::
  408. _display_off::
  409.     ;; Check if the screen is on
  410.     LDH    A,(.LCDC)
  411.     ADD    A
  412.     RET    NC        ; Return if screen is off
  413. 1$:                ; We wait for the *NEXT* VBL 
  414.     LDH    A,(.LY)
  415.     CP    #0x92        ; Smaller than or equal to 0x91?
  416.     JR    NC,1$        ; Loop until smaller than or equal to 0x91
  417. 2$:
  418.     LDH    A,(.LY)
  419.     CP    #0x91        ; Bigger than 0x90?
  420.     JR    C,2$        ; Loop until bigger than 0x90
  421.  
  422.     LDH    A,(.LCDC)
  423.     AND    #0b01111111
  424.     LDH    (.LCDC),A    ; Turn off screen
  425.     RET
  426.  
  427.     ;; Copy OAM data to OAM RAM
  428. .start_refresh_OAM:
  429.     LD    A,#>.OAM
  430.     LDH    (.DMA),A    ; Put A into DMA registers
  431.     LD    A,#0x28        ; We need to wait 160 ns
  432. 1$:
  433.     DEC    A
  434.     JR    NZ,1$
  435.     RET
  436. .end_refresh_OAM:
  437.  
  438.     ;; Serial interrupt
  439. .serial_IO::
  440.     LD    A,(__io_status) ; Get status
  441.  
  442.     CP    #.IO_RECEIVING
  443.     JR    NZ,10$
  444.  
  445.     ;; Receiving data
  446.     LDH    A,(.SB)        ; Get data byte
  447.     LD    (__io_in),A    ; Store it
  448.     LD    A,#.IO_IDLE
  449.     JR    11$
  450.  
  451. 10$:
  452.  
  453.     CP    #.IO_SENDING
  454.     JR    NZ,99$
  455.  
  456.     ;; Sending data
  457.     LDH    A,(.SB)        ; Get data byte
  458.     CP    #.DT_RECEIVING
  459.     JR    Z,11$
  460.     LD    A,#.IO_ERROR
  461.     JR    12$
  462. 11$:
  463.     LD    A,#.IO_IDLE
  464. 12$:
  465.     LD    (__io_status),A ; Store status
  466.  
  467.     XOR    A
  468.     LDH    (.SC),A        ; Use external clock
  469.     LD    A,#.DT_IDLE
  470.     LDH    (.SB),A        ; Reply with IDLE byte
  471. 99$:
  472.     LD    A,#0x80
  473.     LDH    (.SC),A        ; Enable transfer with external clock
  474.     RET
  475.  
  476. _mode::
  477.     LDA    HL,2(SP)    ; Skip return address
  478.     LD    L,(HL)
  479.     LD    H,#0x00
  480.     CALL    .set_mode
  481.     RET
  482.  
  483. _get_mode::
  484.     LD    HL,#.mode
  485.     LD    E,(HL)
  486.     RET
  487.     
  488. _enable_interrupts::
  489.     EI
  490.     RET
  491.  
  492. _disable_interrupts::
  493.     DI
  494.     RET
  495.  
  496. .reset::
  497. _reset::
  498.     LD    A,(__cpu)
  499.     JP    .code_start
  500.  
  501. _set_interrupts::
  502.     DI
  503.     LDA    HL,2(SP)    ; Skip return address
  504.     XOR    A
  505.     LDH    (.IF),A        ; Clear pending interrupts
  506.     LD    A,(HL)
  507.     LDH    (.IE),A
  508.     EI            ; Enable interrupts
  509.     RET
  510.  
  511. _add_VBL::
  512.     PUSH    BC
  513.     LDA    HL,4(SP)    ; Skip return address and registers
  514.     LD    C,(HL)
  515.     INC    HL
  516.     LD    B,(HL)
  517.     CALL    .add_VBL
  518.     POP    BC
  519.     RET
  520.  
  521. _add_LCD::
  522.     PUSH    BC
  523.     LDA    HL,4(SP)    ; Skip return address and registers
  524.     LD    C,(HL)
  525.     INC    HL
  526.     LD    B,(HL)
  527.     CALL    .add_LCD
  528.     POP    BC
  529.     RET
  530.  
  531. _add_TIM::
  532.     PUSH    BC
  533.     LDA    HL,4(SP)    ; Skip return address and registers
  534.     LD    C,(HL)
  535.     INC    HL
  536.     LD    B,(HL)
  537.     CALL    .add_TIM
  538.     POP    BC
  539.     RET
  540.  
  541. _add_SIO::
  542.     PUSH    BC
  543.     LDA    HL,4(SP)    ; Skip return address and registers
  544.     LD    C,(HL)
  545.     INC    HL
  546.     LD    B,(HL)
  547.     CALL    .add_SIO
  548.     POP    BC
  549.     RET
  550.  
  551. _add_JOY::
  552.     PUSH    BC
  553.     LDA    HL,4(SP)    ; Skip return address and registers
  554.     LD    C,(HL)
  555.     INC    HL
  556.     LD    B,(HL)
  557.     CALL    .add_JOY
  558.     POP    BC
  559.     RET
  560.  
  561.     .area    _HEAP
  562. _malloc_heap_start::
  563.